#!/bin/bash

RED='\033[0;31m'
YELLOW0='\033[7;33m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
SKYBLUE='\033[0;36m'
PLAIN='\033[0m'

function error() {
    echo -e "${RED}[ERROR] ${PLAIN}$*"
}
function info() {
    echo -e "${GREEN}[INFO] ${PLAIN}$*"
}
function notice() {
    echo -e "${YELLOW}[NOTICE] ${PLAIN}$*"
}

PARAMETERLIST="--check --create --pack --comments --list --delete --clean --distclean --help help"
#RUNPATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
RUNPATH=$( pwd )
DATE=$(date +%F_%H-%M-%S)
ALLPARAMETER="$*"
NUMPARAMETER="$#"

RUNNAME=$(echo $0 | sed 's/\.\///;s/.*\///')

STOREPATH="rfsnapshots"
BACKPATH="${STOREPATH}/${DATE}"
BACKROOTFSPATH="${BACKPATH}/rootfs"
RSYNCLOGFILE="${BACKPATH}/rsync-log"
COMMENTSFILE="${BACKPATH}/comments"
NOTICEFILE="${BACKPATH}/notice-log"
EXCLUDEFILE="exclude.list"


function sigint_task() {
    if [ ${_taskrunflag} -eq 1 ];then
        error "Task ${BACKPATH} unfinish !! delete..."
        rm -rf ./${BACKPATH}
        notice "delete  [${BACKPATH}] done"
    fi
    exit
}
trap sigint_task SIGINT

function check_root(){
	if [[ $EUID != 0 ]];then
	error "Application needs admin access. "
    error "Please run the application as admin (using 'sudo' or 'su')"
    exit
	fi
}

function do_ClearRootfs() {
    info "clear rootfs..."

    sudo apt autoremove
    sudo apt autoclean
    sudo rm -rf /var/log/*.gz
    sudo rm -rf /var/log/*.1
    sudo rm -rf /var/log/apt/*.gz
    sudo rm -rf /var/log/apt/*.1
    sudo rm -rf /var/lib/apt/lists/*
    sudo cp /dev/null /etc/apt/sources.list
    sudo cp /dev/null /var/log/dmesg
    sudo cp /dev/null /var/log/kern.log
    sudo cp /dev/null /var/log/messages
    sudo cp /dev/null /var/log/syslog
    sudo cp /dev/null /var/log/debug
    sudo cp /dev/null /var/log/btmp
    sudo cp /dev/null /var/log/lastlog
    sudo cp /dev/null /var/log/user.log
    sudo cp /dev/null /var/log/wtmp
    sudo cp /dev/null /var/log/messages
    sudo cp /dev/null /var/log/secure
    sudo cp /dev/null /var/log/aptitude
    sudo cp /dev/null /root/.bash_history
}

function out_help
{
    echo 
    echo -e "${GREEN}Rootfspack v1.0.0 by qrfu (qrfu@linx-info.com)${PLAIN}"
    echo "
Syntax:
    rootfspack --help 
    rootfspack --list
    rootfspack --check
    rootfspack --delete
    rootfspack --distclean    
    rootfspack --create [OPTIONS]

Examples:  

    rootfspack --create --comments=\"fix some bug\" --clean --pack

"
}

function create_excludefiles()
{
cat > ${EXCLUDEFILE} << EOF
/dev/*
/proc/*
/sys/*
/media/*
/mnt/*
/tmp/*
/run/*
/cdrom/*
/lost+found/*
/root/.cache/*
EOF

} 


function check_Excludefiles()
{
	if [ -f $EXCLUDEFILE ];then
		info "find ${EXCLUDEFILE} "
	else
		notice "Not find exclude.list, Use default setting!"
		create_excludefiles;
	fi

	tmp=$(grep -nR "${EXCLUDEFILE}" ${EXCLUDEFILE})
	if [ "$tmp" == "" ];then
		echo "${RUNPATH}/${EXCLUDEFILE}" >> ${EXCLUDEFILE}
	fi
	tmp=$(grep -nR "${STOREPATH}" ${EXCLUDEFILE})
	if [ "$tmp" == "" ];then
		echo "${RUNPATH}/${STOREPATH}" >> ${EXCLUDEFILE}
	fi
	tmp=$(grep -nR "${RUNNAME}" ${EXCLUDEFILE})
	if [ "$tmp" == "" ];then
		echo "${RUNPATH}/${RUNNAME}" >> ${EXCLUDEFILE}
	fi
    sed -i 's/\/\//\//'  ${EXCLUDEFILE}
}

function check_Parameter()
{
    let _errornum=0
    let _taskrunflag=0
    notsupportlist=""

    if [ "X$ALLPARAMETER" == "X" ];then
        out_help;
    fi 
        
    for((k=2;k<${NUMPARAMETER}+2;k++));
    do
        temp=$(echo "echo \" ${ALLPARAMETER} \"   |  awk -F \"--\" '{print \$$k}' " | bash |grep "comments=" )

        if [[ ${temp} =~ "comments" ]];then
            
            COMMENTS=$(echo ${temp} | sed 's/comments=//' )
        fi
    done
    
    MAINPARAMETER=$(echo "echo \" ${ALLPARAMETER} \" | sed 's/=$COMMENTS//' " | bash)

	for i in ${MAINPARAMETER}
	do        
        _checkerrorflag=0;
        
        for j in ${PARAMETERLIST}
        do
            if [ "X$i" == "X$j" ];then
                _checkerrorflag=1
            elif [[ ${i} =~ "--comments=" ]];then
                _checkerrorflag=1
            fi 
        done

        if [ ${_checkerrorflag} -eq 0 ];then
            let _errornum++
            notsupportlist="${notsupportlist} $i"
        fi
        
    done

    if [ ${_errornum} -gt 0 ];then
        error "Invalid command line arguments: ${notsupportlist}"
        out_help;
        exit
    fi  
}

function do_ParsingParameter()
{
    for i in ${ALLPARAMETER}
	do     
        case "$i" in
            --check)        do_check;;
            --create)       do_create;;
            --pack)         do_pack;;
            --distclean)    do_distclean;;
            --list)         do_list;;
            --delete)       do_delete;;
            --help)         out_help;;
            *);;
        esac
    done
}

function do_check()
{
    rsync_version=$(rsync --version 2>/dev/null | grep "version" | awk '{print $3}')

    if [[ $rsync_version == "" ]];then
        error "Please install rsync"
    else
        info "rsync version: $rsync_version\c"
    fi

    TOTALSIZE=$(df -h| grep "/$" | awk '{print $2}')
    USEDSIZE=$(df -h| grep "/$" | awk '{print $3}')
    AVAILSIZE=$(df -h| grep "/$" | awk '{print $4}')
    echo 
    check_Excludefiles;

    echo -e "${GREEN}[INFO]${PLAIN} Total: ${SKYBLUE}${TOTALSIZE}${PLAIN}  Used:${SKYBLUE}${USEDSIZE}${PLAIN}  Avail:${SKYBLUE}${AVAILSIZE}${PLAIN}"
    echo
    
}

function do_create()
{
    check_root
    mkdir -p "${BACKPATH}"
    mkdir -p "${BACKROOTFSPATH}"
    touch ${RSYNCLOGFILE}

    do_check

    if [[ ${ALLPARAMETER} =~ "--clean" ]];then
        do_ClearRootfs;
    fi

    if [[ ${ALLPARAMETER} =~ "comments" ]];then

        echo $COMMENTS > $COMMENTSFILE
    fi
   
    _taskrunflag=1;

    cp ${EXCLUDEFILE} ${BACKPATH}
    
    echo -e "${RED}\c"
	rsync -aii -X -t -a -H -E --recursive --verbose --delete --force --stats --sparse --delete-excluded \
    --log-file=${RSYNCLOGFILE} \
    --exclude-from=${EXCLUDEFILE} \
    --delete-excluded / ${BACKROOTFSPATH} 2>&1  >/dev/null | tee $NOTICEFILE

    echo -e "${PLAIN}"

    _taskrunflag=2;

    echo -e  "${GREEN}[INFO]${PLAIN}snapshots rsync complete ${YELLOW}${BACKPATH}${PLAIN}" 

    if [[ ${ALLPARAMETER} =~ "pack" ]];then
        do_pack $BACKROOTFSPATH
    fi    

    if [[ -s $NOTICEFILE ]];then 
        echo 
        echo -e "${RED}[NOTICE]${PLAIN}There are some errors, please check errorlog : ${RED}${NOTICEFILE}${PLAIN} and full log : ${RED}${RSYNCLOGFILE}${PLAIN}"
    else
        rm $NOTICEFILE 
    fi
}

function do_pack()
{
    if [ "x$*" == "x" ];then
        if [[ ${_taskrunflag} -eq 2 ]];then
           return  
        fi
        info "list pack"
    else
        info "Pack $* "
    fi

    cd $BACKROOTFSPATH/

    sudo tar --xattrs -zcpmf ../rootfs-$DATE.tar.gz ./

    echo -e "${GREEN}[INFO]${PLAIN} Pack finished in ${YELLOW}${BACKPATH}/rootfs-$DATE.tar.gz${PLAIN}"

    cd - > /dev/null 2>&1
}
function do_distclean()
{
    check_root
    info "delete all snapshots..."
    sudo rm -rf ./${STOREPATH} ${EXCLUDEFILE}
}

function do_list()
{
    SNAPSHOTSLIST=$(ls ${STOREPATH} 2>/dev/null )
    count=1
    for i in ${SNAPSHOTSLIST}
    do
        READCOMMENTS=$(cat ${STOREPATH}/${i}/comments 2>/dev/null)
        
        if [[ $READCOMMENTS != "" ]];then
            READCOMMENTS="\"${READCOMMENTS}\""
        fi

        if [[ -f ${STOREPATH}/${i}/rootfs-${i}.tar.gz ]];then
            PACKSTATUS="[PACKED]"
        fi
        echo -e "${SKYBLUE}[$count]${PLAIN} ${i} ${READCOMMENTS}  ${PACKSTATUS}"
        let count++
    done
}

function do_delete ()
{
    check_root
    SNAPSHOTSLIST=$(ls ${STOREPATH} 2>/dev/null )
    SNAPSHOTSNUM=$(ls ${STOREPATH} 2>/dev/null | wc -l 2>/dev/null)

    if [[ ${SNAPSHOTSNUM} -eq 0 ]];then
        notice "not find snapshot"
        exit
    fi
    count=0
    for i in ${SNAPSHOTSLIST}
    do
        let count++
        SNAPSHOTSNAME[$count]=$i
        READCOMMENTS=$(cat ${STOREPATH}/${i}/comments 2>/dev/null)
        if [[ $READCOMMENTS != "" ]];then
            READCOMMENTS="\"${READCOMMENTS}\""
        fi

        if [[ -f ${STOREPATH}/${i}/rootfs-${i}.tar.gz ]];then
            PACKSTATUS="[PACKED]"
        fi
        echo -e "${SKYBLUE}[$count]${PLAIN} ${i} ${READCOMMENTS}  ${PACKSTATUS}"
    done

    echo -e "${YELLOW}Please input the number to delete【1-${count}】: \c"
	read  number

    if [[ 'number' -gt ${count} || 'number' -lt 1 ]];then

		echo -e "${RED}Please input correct number【1-${count}】!${YELLOW}"
	else
        sudo rm -rf ${STOREPATH}/${SNAPSHOTSNAME[$number]}
	fi
}

check_Parameter
do_ParsingParameter
